package com.cryptoneedle.center.ods.service;

import com.cryptoneedle.center.common.entity.mapping.MappingColumn;
import com.cryptoneedle.center.common.entity.mapping.MappingTable;
import com.cryptoneedle.center.common.entity.ods.OdsColumn;
import com.cryptoneedle.center.common.entity.ods.OdsTable;
import com.cryptoneedle.center.common.key.ColumnKey;
import com.cryptoneedle.center.common.key.TableKey;
import com.cryptoneedle.center.common.repository.mapping.MappingColumnRepository;
import com.cryptoneedle.center.common.repository.mapping.MappingTableRepository;
import com.cryptoneedle.center.ods.entity.ods.OdsMappingColumn;
import com.cryptoneedle.center.ods.entity.ods.OdsMappingTable;
import com.cryptoneedle.center.ods.service.ods.OdsColumnService;
import com.cryptoneedle.center.ods.service.ods.OdsMappingColumnService;
import com.cryptoneedle.center.ods.service.ods.OdsMappingTableService;
import com.cryptoneedle.center.ods.service.ods.OdsTableService;
import com.cryptoneedle.center.ods.vo.BindMappingTableVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>description:  </p>
 *
 * @author CryptoNeedle
 * @date 2025-09-26
 */
@Service
@Slf4j
public class OdsMappingService {

    @Resource
    private OdsTableService odsTableService;

    @Resource
    private OdsColumnService odsColumnService;

    @Resource
    private OdsMappingTableService odsMappingTableService;

    @Resource
    private OdsMappingColumnService odsMappingColumnService;

    @Resource
    private MappingTableRepository mappingTableRepository;

    @Resource
    private MappingColumnRepository mappingColumnRepository;

    @Transactional(rollbackFor = Exception.class)
    public void bindMappingTable(BindMappingTableVo bindMappingTableVo) {
        TableKey odsTableKey = bindMappingTableVo.getOdsTableKey();
        TableKey mappingTableKey = bindMappingTableVo.getMappingTableKey();
        Boolean bindMappingTableFlag = bindMappingTableVo.getBindMappingTableFlag();
        List<BindMappingTableVo.BindColumn> bindColumnList = bindMappingTableVo.getBindColumnList();

        // 获取ODS表
        OdsTable odsTable = odsTableService.getById(odsTableKey);
        if (odsTable == null) {
            throw new RuntimeException("OdsTable not found");
        }

        // 获取映射表
        MappingTable mappingTable = mappingTableRepository.findById(mappingTableKey).orElse(null);
        if (mappingTable == null) {
            throw new RuntimeException("MappingTable not found");
        }
        if (!mappingTable.getMappingTableFlag()) {
            throw new RuntimeException("MappingTable is not mapping table");
        }

        List<MappingColumn> mappingColumnList = mappingColumnRepository.listCodeByTable(mappingTableKey.getCatalogName(), mappingTableKey.getDatabaseName(), mappingTableKey.getTableName());
        // ODS表映射关系
        OdsMappingTable odsMappingTable = new OdsMappingTable()
                .setCatalogName(odsTableKey.getCatalogName())
                .setDatabaseName(odsTableKey.getDatabaseName())
                .setTableName(odsTableKey.getTableName())
                .setMappingCatalogName(mappingTableKey.getCatalogName())
                .setMappingDatabaseName(mappingTableKey.getDatabaseName())
                .setMappingTableName(mappingTableKey.getTableName());

        // 配置映射关系
        if (bindMappingTableFlag) {
            if (bindColumnList == null || bindColumnList.isEmpty()) {
                throw new RuntimeException("BindColumnList is empty");
            }

            // 检查字段是否映射全
            Set<String> mappingColumnSet = mappingColumnList
                    .stream()
                    .map(MappingColumn::getColumnName)
                    .collect(Collectors.toSet());
            Set<String> bindColumnNameSet = bindColumnList.stream()
                    .map(BindMappingTableVo.BindColumn::getMappingColumnName)
                    .collect(Collectors.toSet());
            if (!bindColumnNameSet.containsAll(mappingColumnSet)) {
                throw new RuntimeException("BindColumnList is not contain MappingColumnList");
            }

            odsMappingTableService.save(odsMappingTable);

            // ODS列映射关系
            for (BindMappingTableVo.BindColumn bindColumn : bindColumnList) {
                String odsColumnName = bindColumn.getOdsColumnName();
                String mappingColumnName = bindColumn.getMappingColumnName();
                if (StringUtils.isBlank(odsColumnName)) {
                    throw new RuntimeException("odsColumnName is empty");
                }
                if (StringUtils.isBlank(mappingColumnName)) {
                    throw new RuntimeException("mappingColumnName is empty");
                }

                OdsMappingColumn odsMappingColumn = new OdsMappingColumn()
                        .setCatalogName(odsTableKey.getCatalogName())
                        .setDatabaseName(odsTableKey.getDatabaseName())
                        .setTableName(odsTableKey.getTableName())
                        .setColumnName(odsColumnName)
                        .setMappingCatalogName(mappingTableKey.getCatalogName())
                        .setMappingDatabaseName(mappingTableKey.getDatabaseName())
                        .setMappingTableName(mappingTableKey.getTableName())
                        .setMappingColumnName(mappingColumnName);

                ColumnKey columnKey = odsMappingColumn.getColumnKey();
                OdsColumn odsColumn = odsColumnService.getById(columnKey);
                if (odsColumn == null) {
                    throw new RuntimeException("OdsColumn not found");
                }

                ColumnKey mappingKey = odsMappingColumn.getMappingKey();
                MappingColumn mappingColumn = mappingColumnRepository.findById(mappingKey).orElse(null);
                if (mappingColumn == null) {
                    throw new RuntimeException("MappingColumn not found");
                }

                odsMappingColumnService.save(odsMappingColumn);
            }
        } else {
            odsMappingTableService.delete(odsMappingTable);
            odsMappingColumnService.deleteByOdsMappingTable(
                    odsMappingTable.getCatalogName(),
                    odsMappingTable.getDatabaseName(),
                    odsMappingTable.getTableName(),
                    odsMappingTable.getMappingCatalogName(),
                    odsMappingTable.getMappingDatabaseName(),
                    odsMappingTable.getMappingTableName()
            );
        }
    }
}